package com.eyealike.client.util;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class SecurityUtils
{
	private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";

	public final static String AWS_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss Z";

	public static String computeDigest( final String msg, final String secretKey )
	{
		final byte[] rawKey = secretKey.getBytes();

		final SecretKeySpec signingKey = new SecretKeySpec( rawKey, HMAC_SHA1_ALGORITHM );

		// get an hmac_sha1 Mac instance and initialize with the signing key
		try {
			final Mac mac = Mac.getInstance( HMAC_SHA1_ALGORITHM );
			mac.init( signingKey );
			final byte[] rawHmac = mac.doFinal( msg.getBytes( "UTF-8" ) );

			// base64-encode the hmac
			return Base64.base64Encode( rawHmac );
		} catch( final NoSuchAlgorithmException e ) {
			throw new RuntimeException( e );
		} catch( final InvalidKeyException e ) {
			throw new RuntimeException( e );
		} catch( final UnsupportedEncodingException e ) {
			throw new RuntimeException( e );
		}
	}

	public static String getUTCString()
	{
		final DateFormat df = new SimpleDateFormat( AWS_DATE_FORMAT );
		df.setTimeZone( TimeZone.getTimeZone( "UTC" ) );

		return df.format( new Date() );
	}

	public static String createAuthorizationHeader(
		final String accessId,
		final String secretKey,
		final String serviceId,
		final Iterable<String> queryIds,
		final Iterable<String> roiIds,
		final Iterable<String> collectionIds,
		final Iterable<String> classifierCodes,
		final String requestDate )
	{
		final String msg =
			computeSignableMessage( accessId, serviceId, queryIds, roiIds, collectionIds, classifierCodes, requestDate );

		final String digest = computeDigest( msg, secretKey );

		return "EYEALIKE " + accessId + " " + digest;
	}

	public static String computeSignableMessage(
		final String accessId,
		final String serviceId,
		final Iterable<String> queryIds,
		final Iterable<String> roiIds,
		final Iterable<String> collectionIds,
		final Iterable<String> classifierCodes,
		final String requestDate )
	{
		final StringBuilder signedMessage = new StringBuilder();
		signedMessage.append( accessId );
		signedMessage.append( "\n" );
		signedMessage.append( serviceId );
		signedMessage.append( "\n" );

		if( queryIds != null ) {
			for( final String url : queryIds ) {
				signedMessage.append( url );
				signedMessage.append( "\n" );
			}
		}

		if( roiIds != null ) {
			for( final String c : roiIds ) {
				signedMessage.append( c );
				signedMessage.append( "\n" );
			}
		}

		if( collectionIds != null ) {
			for( final String c : collectionIds ) {
				signedMessage.append( c );
				signedMessage.append( "\n" );
			}
		}

		if( classifierCodes != null ) {
			for( final String c : classifierCodes ) {
				signedMessage.append( c );
				signedMessage.append( "\n" );
			}
		}

		signedMessage.append( requestDate.trim() );

		return signedMessage.toString();
	}
}
